<template>
  <div
    class="div1"
    :style="{
      backgroundImage: _backgroundImage
        ? `url('${_backgroundImage}')`
        : `url('https://img2.baidu.com/it/u=3602890503,1890231107&fm=253&fmt=auto&app=138&f=JPEG')`
    }"
    ref="divRef"
  >
    <div class="img_content">
      <img class="_img" v-for="(link, index) in links" :key="index" :src="link?.positionImg" />
    </div>
    <el-button
      size="large"
      :loading="loading"
      type="primary"
      :disabled="links?.length > 0 ? false : true"
      round
      @click="startAnimation"
      class="_button"
    >
      {{ buttonText() }}
    </el-button>
  </div>
</template>

<script setup>
import { getLotteryListApi } from '@/api/lottery'
import { getData } from '@/api/system/dict/data'
import { ref, onMounted } from 'vue'

const divRef = ref(null)
const loading = ref(false)
const _backgroundImage = ref()
const links = ref([])
const animationRunning = ref(false)
let radius = 200
let dtr = Math.PI / 180
let d = 300
let mcList = []
let lasta = 1
let lastb = 1
let distr = true
let tspeed = 20
let randomX = 0
let randomY = 0
let howElliptical = 1
let aA = null
let oDiv = null
let updateTimeId = ref(null)
let randomScrollingTimeId = ref(null)

onMounted(init)
function init() {
  if (links.value.length > 0) {
    oDiv = divRef.value
    aA = Array.from(oDiv.getElementsByTagName('img'))
    for (let i = 0; i < aA.length; i++) {
      const oTag = {
        offsetWidth: aA[i].offsetWidth,
        offsetHeight: aA[i].offsetHeight,
        cx: 0, // 添加 cx 属性
        cy: 0, // 添加 cy 属性
        cz: 0 // 添加 cz 属性
      }
      mcList.push(oTag)
    }

    sineCosine(0, 0, 0)
    positionAll()
    updateTimeId.value = setInterval(update, 100)
  } else {
    setTimeout(init, 200)
  }
}
function randomScrolling() {
  randomScrollingTimeId.value = setInterval(() => {
    // 生成随机的滚动方向
    randomX = Math.random() > 0.5 ? 1 : -1
    randomY = Math.random() > 0.5 ? 1 : -1
  }, 200)
}
randomScrolling()
function update() {
  if (!animationRunning.value) return // 只有当 animationRunning 为真时才更新

  let a = randomX * tspeed
  let b = randomY * tspeed
  lasta = a
  lastb = b

  if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) {
    return
  }

  let c = 0
  sineCosine(a, b, c)
  doRotation()
  doPosition()
  depthSort()
}

function depthSort() {
  aA.sort((vItem1, vItem2) => {
    if (vItem1.cz > vItem2.cz) {
      return -1
    } else if (vItem1.cz < vItem2.cz) {
      return 1
    } else {
      return 0
    }
  })

  aA.forEach((item, i) => {
    item.style.zIndex = i
  })
}
function handleResize() {
  // 获取 img_content 的尺寸
  const imgContentRect = oDiv.querySelector('.img_content').getBoundingClientRect()

  for (let i = 0; i < mcList.length; i++) {
    const x = mcList[i].cx + oDiv.offsetWidth / 2 - mcList[i].offsetWidth / 2
    const y = mcList[i].cy + oDiv.offsetHeight / 2 - mcList[i].offsetHeight / 2

    // 检查是否超出 img_content 边界
    const xMin = imgContentRect.left + mcList[i].offsetWidth / 2
    const xMax = imgContentRect.right - mcList[i].offsetWidth / 2
    const yMin = imgContentRect.top + mcList[i].offsetHeight / 2
    const yMax = imgContentRect.bottom - mcList[i].offsetHeight / 2

    // 如果超出边界，则调整位置
    const clampedX = Math.max(xMin, Math.min(x, xMax))
    const clampedY = Math.max(yMin, Math.min(y, yMax))

    aA[i].style.left = `${clampedX}px`
    aA[i].style.top = `${clampedY}px`
  }
}
onMounted(() => {
  window.addEventListener('resize', handleResize)
})
import { onUnmounted } from 'vue'
onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
  clearInterval(updateTimeId.value)
  clearInterval(randomScrollingTimeId.value)
})
function positionAll() {
  const max = mcList.length
  const aTmp = []
  const oFragment = document.createDocumentFragment()

  // 随机排序
  aA.forEach((item) => aTmp.push(item))
  aTmp.sort(() => Math.random() - 0.5)

  aTmp.forEach((item) => oFragment.appendChild(item))

  oDiv.appendChild(oFragment)

  for (let i = 1; i < max + 1; i++) {
    let phi, theta
    if (distr) {
      phi = Math.acos(-1 + (2 * i - 1) / max)
      theta = Math.sqrt(max * Math.PI) * phi
    } else {
      phi = Math.random() * Math.PI
      theta = Math.random() * (2 * Math.PI)
    }

    mcList[i - 1].cx = radius * Math.cos(theta) * Math.sin(phi)
    mcList[i - 1].cy = radius * Math.sin(theta) * Math.sin(phi)
    mcList[i - 1].cz = radius * Math.cos(phi)

    aA[i - 1].style.left = `${
      mcList[i - 1].cx + oDiv.offsetWidth / 2 - mcList[i - 1].offsetWidth / 2
    }px`
    aA[i - 1].style.top = `${
      mcList[i - 1].cy + oDiv.offsetHeight / 2 - mcList[i - 1].offsetHeight / 2
    }px`
  }
}

function doPosition() {
  const l = oDiv.offsetWidth / 2
  const t = oDiv.offsetHeight / 2

  mcList.forEach((item, i) => {
    aA[i].style.left = `${item.x + l - item.offsetWidth / 2}px` // 使用 item.x 替换 item.cx
    aA[i].style.top = `${item.y + t - item.offsetHeight / 2}px` // 使用 item.y 替换 item.cy

    aA[i].style.fontSize = `${Math.ceil((12 * item.scale) / 2) + 8}px`

    aA[i].style.filter = `alpha(opacity=${100 * item.alpha})`
    aA[i].style.opacity = item.alpha
  })
}

function doRotation() {
  // 计算当前的旋转角度

  const { sa, ca, sb, cb, sc, cc } = sineCosine(lasta, lastb, 0) // 使用 lasta 和 lastb 作为当前的角度

  mcList.forEach((item) => {
    let rx1 = item.cx
    let ry1 = item.cy * ca + item.cz * -sa
    let rz1 = item.cy * sa + item.cz * ca

    let rx2 = rx1 * cb + rz1 * sb
    let ry2 = ry1
    let rz2 = rx1 * -sb + rz1 * cb

    let rx3 = rx2 * cc + ry2 * -sc
    let ry3 = rx2 * sc + ry2 * cc
    let rz3 = rz2

    item.cx = rx3
    item.cy = ry3
    item.cz = rz3

    const per = d / (d + rz3)

    item.x = howElliptical * rx3 * per - howElliptical * 2
    item.y = ry3 * per
    item.scale = per
    item.alpha = per

    item.alpha = (item.alpha - 0.6) * (10 / 6)
  })
}

function sineCosine(a, b, c) {
  const sa = Math.sin(a * dtr)
  const ca = Math.cos(a * dtr)
  const sb = Math.sin(b * dtr)
  const cb = Math.cos(b * dtr)
  const sc = Math.sin(c * dtr)
  const cc = Math.cos(c * dtr)

  return { sa, ca, sb, cb, sc, cc }
}
function getList() {
  getLotteryListApi({
    pageNum: 1,
    pageSize: 9999
  }).then((res) => {
    links.value = res.data.rows?.filter((item) => item.status === 0) || []
    console.log(links.value)
  })
}
function getBgcImage() {
  getData(166).then((res) => {
    _backgroundImage.value = res.data.remark
  })
}
function buttonText() {
  if (animationRunning.value && links.value.length > 0) {
    return '停 止'
  } else if (!animationRunning.value && links.value.length > 0) {
    return '开 始'
  } else if (links.value.length <= 0) {
    return '暂无数据'
  }
}
function startAnimation() {
  loading.value = true
  update()
  animationRunning.value = !animationRunning.value
  setTimeout(() => {
    animationRunning.value = !animationRunning.value
    emits('init')
    loading.value = false
  }, 3000)
}

defineExpose({
  getList
})
getList()
getBgcImage()
const emits = defineEmits(['init'])
</script>

<style lang="scss" scoped>
.div1 {
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  position: relative;
  width: 100%;
  height: calc(100vh - 84px);
  display: flex;
  justify-content: center;
  align-items: center;
  display: flex;
  justify-content: center;
  align-items: center;
}
.img_content {
  position: relative;
  min-width: 800px;
  min-height: 800px;
  overflow: hidden;
}
._img {
  position: absolute;
  top: 0px;
  left: 0px;
  font-family: Microsoft YaHei;
  font-weight: bold;
  text-decoration: none;
  padding: 3px 6px;
}
._img {
  width: 240px;
  height: 160px;
  border-radius: 10px;
}
._button {
  position: absolute;
  bottom: 50px;
  left: 50%;
  transform: translateX(-50%);
}
</style>
